/*
 * RootSearch.cpp
 *
 *  Created on: 14.04.2011
 *      Author: ed
 */

#include "RootSearch.hh"
#include "PrimariesGenerator.hh"
#include "globals.hh"
#include "Sample.hh"
#include "stdio.h"
using namespace std;
RootSearch::RootSearch(IExperimentalVolume *Volume,G4RunManager *RunManager)
{
	vol = Volume;
	runManager = RunManager;
	antiWrongDecisionFactor = 50;
	missCount = 0;
	left = new stack<Sample*>();
	right = new stack<Sample*>();
}
G4double RootSearch::Root(G4double lCExp,G4double lSc,G4double epsilon,G4double l,G4double r)
{
	Sample* sr = new Sample(r);
	Sample* sl = new Sample(l);
	vol->SetLSc(lSc);
	vol->SetLAbs(l);
	/*for(int i = 0;i< antiWrongDecisionFactor;i++)
	{
		runManager->BeamOn(1);
		sl->AddExperiment(vol->GetLightCollection());

	}*/
	while(sl->GetNPQ()<antiWrongDecisionFactor)
	{
		runManager->BeamOn(1);
		sl->AddExperiment(vol->GetLightCollection());
		if(sl->GetNPassedParticles()>1000)
			break;
		cout<<*sl<<endl;
	}
	sl -> k = std::numeric_limits<double>::max();
	vol->SetLAbs(r);
	/*for(int i = 0;i< antiWrongDecisionFactor;i++)
	{
		runManager->BeamOn(1);
		sr->AddExperiment(vol->GetLightCollection());
	}*/
	while(sr->GetNPQ()<antiWrongDecisionFactor)
	{
		runManager->BeamOn(1);
		sr->AddExperiment(vol->GetLightCollection());
		cout<<*sr<<endl;
	}
	sr -> k = std::numeric_limits<double>::max();

	Sample* sm = new Sample(RootSearch::GetZero(sl,sr,lCExp));
	sm->k = RootSearch::GetK(sl,sr);
	G4cout<<"-----------------"<<*sl<<*sm<<*sr<<"-----------------"<<G4endl;
	vol->SetLAbs(sm->GetLAbs());
	G4int iterations = 0;
	while(true)
	{
		runManager->BeamOn(1);
		sm->AddExperiment(vol->GetLightCollection());
		G4cout<<*sm<<G4endl;
		if(abs(sm->GetLC()-lCExp)>sm->GetError())
		{
			if(sm->GetLC()<lCExp)
			{
				G4double k = RootSearch::GetK(sl,sr);
				G4double zero = RootSearch::GetZero(sm,sr,lCExp);
				left->push(sl);
				sl = sm;
				sm->k = k;
				sm = new Sample(zero);
				vol->SetLAbs(zero);
			}
			else
			{
				G4double k = RootSearch::GetK(sl,sr);
				G4double zero = RootSearch::GetZero(sl,sm,lCExp);
				right->push(sr);
				sr = sm;
				sm = new Sample(zero);
				sm->k = k;
				vol->SetLAbs(zero);
			}
			continue;
		}
		if(abs(sm->GetLC()-lCExp)>sm->GetError())
		{
			return sm->GetLAbs();
		}

	}
	return 0;
}
G4double RootSearch::GetZero(Sample* sl, Sample* sr,G4double lCExp)
{
	G4double k = RootSearch::GetK(sl,sr);
	G4double b = sl->GetLC() - k * sl->GetLAbs()-lCExp;
	return -b/k;
}
RootSearch::~RootSearch()
{
	delete left;
	delete right;
}
